iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

從 TouchableOpacity 認識事件處理

在上一段我們介紹了許多元件,不過並沒有介紹怎樣讓按鈕按下後執行某些事,或是怎樣改變 TextInput 的 value 值。先讓我們回到 HTML 的世界看看我們過去是怎樣觸發事件的:

<button onclick="console.log('click')">按鈕</button>

當點擊這個按鈕時,會在 console 面板印出 click 的字串。那麼,在 JSX 中,要怎樣改寫上面的程式碼呢?答案是把 onclick 改成小駝峰寫法,用大括號包覆 JS 的處理。並且最重要的一點是,如果需要傳入參數,那就要用箭頭函式來撰寫,才會正確的在點擊時才被觸發。

{/* 正確寫法:只有點擊按鈕時,才會觸發 console.log('click') */}
<button onClick={() => console.log('click')}>按鈕</button>
{/* 錯誤寫法:第一次渲染就觸發 console.log('click) ,之後點擊按鈕都不會有任何 console.log() */}
<button onClick={console.log('click')}>按鈕</button>

如果你並沒有要傳入參數,只是呼叫一個函式,那也可以不用以箭頭函式撰寫:

function App() {
  const handleClick = () => {
    console.log('click');
  };
  const handleClick2 = param => {
    console.log(param);
  };
  return (
    {/* 正確寫法*/}
    <button onClick={handleClick}>按鈕</button>
    {/* 也是正確寫法*/}
    <button onClick={() => handleClick()}>按鈕</button>
    {/* 函式傳入參數的寫法*/}
    <button onClick={() => handleClick2('click')}>按鈕</button>

回到 React Native 的按鈕 TouchableOpacity ,我們不能使用 onClick 來處理事件,因為手機是用手去 press 而不是 click 。因此要這樣改寫:

<TouchableOpacity onPress={() => console.log('pressed')}>
  <Text>這是一個按鈕</Text>
</TouchableOpacity>

Tips :以防你學到這邊對 JSX 的幾個重要特性還沒辦法駕輕就熟,讓我簡單統整一下。

  1. 最外層只能有一個根元件。
  2. 要渲染變數、載入樣式、呼叫事件、執行一段 JS 時,都要用一個大括號來包覆。例如: style={styles.dangerText} / onPress={handlePress}
  3. 樣式被包在物件當中,有兩個以上時以逗號隔開。屬性要用小駝峰寫法,值除了數字都要用字串來傳遞。例如 {fontSize: 20, color: ‘red’}
  4. 事件處理的事件觸發方式要用小駝峰寫法。要傳入參數時,需改寫為箭頭函式,否則無法正確觸發。例如: onPress={()=>console.log(‘pressed’)}

從 TextInput 認識 State 與 setState

在前面,我們撰寫了簡單的程式碼來載入一個 TextInput ,就像這樣:

function App() {
  const text = 'input value';

  return (
      <TextInput value={text} />
  );
}

要讓 TextInput 的值改變,就必須去更動 value 綁定的 text 變數。我們應該如何正確的在 React 中更新一個變數的值呢?首先,在 React 中,我們將這些資料稱呼為 State 。要更動 State ,只能夠透過 setState() 賦予一個新的值。因此,在繼續談 TextInput 的範例前,我們先岔出來聊聊 State 和 setState() 。

從 React 16.8 後,發展出 Hooks ,也就是 React 提供開發者一些小工具,讓我們能快速達到某些效果。而 useState() 就是其中之一。他最主要的目的,是讓我們初始化一個 State ,讓我們能自由的命名 State 和用來更新該 State 的方法(過往統一被稱為 setState)。舉例來說:

import React, {useState} from 'react';

function App() {
  const [text, setText] = useState('input value');

在上方的程式碼中,我們宣告了一個名為 text 的變數,用 useState 使他的初始值為字串 input value 。並且提供一個名叫 setText 的方法,能透過呼叫他來更新 text 的值。

使用 Hooks 有幾個注意事項,包含:

  1. 只能在 React 的 Functional Component 中使用,不可在自己撰寫的函式中使用。
import React, {useEffect, useState} from 'react';
import Card from './components/Card';
import TypeSelector from './components/TypeSelector';
import {View, SafeAreaView, ScrollView, StyleSheet} from 'react-native';

// 錯誤寫法:
const [wrongExample, setWrongExample] = useState('錯誤');

function App() {
// 正確寫法:
const [correctExample, setCorrectExample] = useState('正確');
// 錯誤寫法:
const wrongExampleFunction = () =>{
  const [wrongExample, setWrongExample] = useState('錯誤');
}
  1. 以 use + 大寫開頭,如 useState 、 useEffect …
  2. 不能在迴圈、條件式、巢狀 function 裡呼叫,因為會導致 React 呼叫順序錯亂。
const wrongExampleFunction = () => {
  if (true) {
    const [wrongExample, setWrongExample] = useState('錯誤');
  }
};

const wrongExampleFunction2 = () => {
  for (let i = 0; i < 3; i++) {
    const [wrongExample2, setWrongExample2] = useState('錯誤');
  }
};

運用上一節所學到的事件處理,設計一個按鈕,按下去的時候呼叫 setText() 。可以觀察到按下去後, text 的值被更新,畫面也更新了:

import React, {useState} from 'react';
import {
  SafeAreaView,
  View,
  TextInput,
  Text,
  TouchableOpacity,
} from 'react-native';

function App() {
  const [text, setText] = useState('input value');

  return (
    <SafeAreaView>
      <View>
        <TextInput value={text} />
        <TouchableOpacity onPress={() => setText('input value changed')}>
          <Text>按下去改變 input 值</Text>
        </TouchableOpacity>

https://ithelp.ithome.com.tw/upload/images/20230911/20129635AQPRrEwP4Y.png
https://ithelp.ithome.com.tw/upload/images/20230911/201296356SQr3Qna1t.png

接著問題就剩下怎樣在每次 input 內容改變時,更新 text 值,好讓 TextInput 可以即時顯示出正確的內容。這時我們會需要用到 onChangeText 這個事件,他的參數會直接等同於目前新的值,因此只要傳入這個新的值,就能正確同步更新 text 了。

<TextInput value={text} onChangeText={newText => setText(newText)} />

寫習慣 HTML 可能會直覺先想到使用 onChange ,而不是 onChangeText 。事實上, React Native 的 TextInput 的確也能使用 onChange 來監聽沒錯,不過他取得值的方式較為複雜。因此直接使用 onChangeText 會比較直觀,也方便撰寫。

<TextInput
  value={text}
  onChange={({nativeEvent: {eventCount, target, text}}) =>
    console.log(text)
  }
/>

到這裡為止,雖然對 State 、 setState 、 useState 還矇矇懂懂,但你已經掌握基礎實作。我會用下面的章節深入介紹 useState 是怎樣讓我們能自己定義變數 text 和 setText ? React 又是怎樣處理資料更新機制?


上一篇
Day 08. 常見元件介紹
下一篇
Day 10. 深入了解 React 更新 State 機制
系列文
即使明天老闆突然叫你用 React Native 也可以跟他說好沒問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言